#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include "lock.h"
#include "common.h"


const int DefaultBlockCount = 0xff;
const int DefaultChunkSize = 4096;
const int DefaultSmallObjSize = 4*1024;
struct chunk
{
    void init(uint32 blocksize, unsigned char blockcount);
    void release();
    void *alloc( uint32 blocksize );
    void dealloc( void* p, uint32 blocksize );
    unsigned char* pData_;
    unsigned char firstFree_;
    unsigned char blockCount_;
};

class FixedAllocator
{
public:
    FixedAllocator();
    FixedAllocator( uint32 blocksize , unsigned char blockcount );
    ~FixedAllocator();
    void Initialize( uint32 blocksize, unsigned char blockcount );
    void *Allocate();
    void Dealloc( void* p );
    void Release();
    uint32 blocksize_;
    unsigned char blockcount_;
private:
    typedef std::vector<chunk> Chunks;
    Chunks chunks_;
    chunk* allocChunk_;
    chunk* deallocChunk_;
};

class SmallObjAllocator
{
public: 
    void *Allocate( uint32 numBytes );
    void Dealloc( void* p, uint32 size );
    static SmallObjAllocator &Instance()
    {
        if( !m_pInstance )
        {
            if( m_bDestroyed )
                OnDeadReference();
            else
                Create();
        }
        return *m_pInstance;
    }
private:
    static void Create()
    {
        //static SmallObjAllocator s_Instance;
        //m_pInstance = &s_Instance;
        m_pInstance = new SmallObjAllocator;
    }
    static void OnDeadReference()
    {
        throw std::runtime_error( "Dead reference detected" );
        return;
    }
    SmallObjAllocator();
    SmallObjAllocator(const SmallObjAllocator &) {};
    SmallObjAllocator operator=(const SmallObjAllocator &) {};
    ~SmallObjAllocator();
    uint32 chunksize_;
    uint32 maxobjsize_;
    static SmallObjAllocator *m_pInstance;
    static bool m_bDestroyed;
    FixedAllocator pool_[DefaultSmallObjSize];
    CLock m_lock;
};

class SmallObject
{
public:
    static void *operator new( std::size_t size );
    static void operator delete( void *p, std::size_t size );
    ~SmallObject() {};
};
#endif